const ACCOUNT = "18040585033";
const PASSWORD = "q461309827";
const QQ = "3024412629";
const PACKAGE_ID_QQ = "com.tencent.mobileqq";               // QQ
const PACKAGE_ID_DD = "com.alibaba.android.rimet";          // 钉钉
const PACKAGE_ID_TASKER = "net.dinglisch.android.taskerm";  // Tasker

const LOWER_BOUND = 1 * 60 * 1000; // 最小等待时间：1min
const UPPER_BOUND = 5 * 60 * 1000; // 最大等待时间：5min

// 执行时的屏幕亮度(0-255),需要"修改系统设置"权限
const SCREEN_BRIGHTNESS = 20;

// 是否过滤通知
const NOTIFICATIONS_FILTER = true;

// PackageId白名单
const PACKAGE_ID_WHITE_LIST = [PACKAGE_ID_QQ, PACKAGE_ID_DD, PACKAGE_ID_TASKER];

// 公司的钉钉CorpId, 获取方法见 2020-09-24 更新日志。如果只加入了一家公司, 可以不填
const CORP_ID = "";

// 锁屏意图, 配合 Tasker 完成锁屏动作
const ACTION_LOCK_SCREEN = "autojs.intent.action.LOCK_SCREEN";

// 监听音量+键, 开启后无法通过音量+键调整音量, 按下音量+键：结束所有子线程
const OBSERVE_VOLUME_KEY = true;

const WEEK_DAY = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

const globalLogFilePath = "/sdcard/脚本/钉钉自动打卡/Archive/" + getCurrentDate() + "-log.txt";

const DelayTime = 10000;

// =================== ↓↓↓ 主线程：监听通知 ↓↓↓ ====================

// 当前时间不戳
let currentDate = new Date();

// 检查无障碍权限
auto.waitFor();

// 创建运行日志
console.setGlobalLogConfig({ file: globalLogFilePath });

// 监听本机通知
events.observeNotification()
events.on("notification", function (n) { notificationHandler(n); });

events.setKeyInterceptionEnabled("volume_up", OBSERVE_VOLUME_KEY);
if (OBSERVE_VOLUME_KEY) {
  events.observeKey();
};

// 监听音量+键
events.onKeyDown("volume_up", function (event) {
  threads.shutDownAll();
  device.setBrightnessMode(1);
  device.cancelKeepingAwake();
  toast("已中断所有子线程!");
});

toastLog("监听中, 请在日志中查看记录的通知及其内容");

// 监听退出事件
events.on("exit", function () { home(); });

// =================== ↑↑↑ 主线程：监听通知 ↑↑↑ =====================

/**
 * 唤醒屏幕
 */
function brightScreen() {
  console.log("唤醒设备");

  //device.setBrightnessMode(0); // 手动亮度模式
  //device.setBrightness(SCREEN_BRIGHTNESS);
  device.wakeUpIfNeeded(); // 唤醒设备
  //device.keepScreenOn(); // 保持亮屏
  sleep(1000); // 等待屏幕亮起

  if (!device.isScreenOn()) {
    console.warn("设备未唤醒, 重试");
    device.wakeUpIfNeeded();
    brightScreen();
  }
  else {
    console.info("设备已唤醒");
  }
  sleep(1000);
}

/**
 * 解锁屏幕
*/
function unlockScreen() {
  console.log("解锁屏幕");

  if (isDeviceLocked()) {
    gesture(320, // 滑动时间：毫秒
      [
        device.width * 0.5,     // 滑动起点 x 坐标：屏幕宽度的一半
        device.height * 0.8     // 滑动起点 y 坐标：距离屏幕底部 10% 的位置
      ],
      [
        device.width * 0.5,     // 滑动终点 x 坐标：屏幕宽度的一半
        device.height * 0.2     // 滑动终点 y 坐标：距离屏幕顶部 10% 的位置
      ]
    );
    //swipe(500, 2000, 500, 1000, 220);

    sleep(1000);
    home();
    sleep(1000);
  }

  if (isDeviceLocked()) {
    console.error("上滑解锁失败,请按脚本中的注释调整 gesture(time, [x1,y1], [x2,y2]) 方法的参数!");
    return;
  }
  console.info("屏幕已解锁");
}

/**
 * 锁屏
 */
function lockScreen() {
  console.log("关闭屏幕");
  //sleep(1000);
  //device.setBrightnessMode(1);
  //sleep(1000);
  //device.cancelKeepingAwake();

  // 锁屏方案1：Root
  // Power();

  // 锁屏方案2：No Root
  swipe(950, 50, 500, 750, 1000);
  sleep(2000);
  click(180, 1300);

  // 万能锁屏方案：向Tasker发送广播, 触发系统锁屏动作
  // app.sendBroadcast({ action: ACTION_LOCK_SCREEN });
  // if (isDeviceLocked()) {
  //     console.info("屏幕已关闭");
  // }
  // else {
  //     console.error("屏幕未关闭, 请尝试其他锁屏方案, 或等待屏幕自动关闭");
  // }
}

function openDingtalk() {
  if (currentPackage() == PACKAGE_ID_DD) {
    console.log("已经在" + app.getAppName(PACKAGE_ID_DD) + "里");
    return;
  }
  app.launchPackage(PACKAGE_ID_DD);
  console.log("正在启动" + app.getAppName(PACKAGE_ID_DD) + "...");
  sleep(10000);
}

function shutdownDingtalk() {
  app.openAppSetting(PACKAGE_ID_DD);
  text("钉钉").waitFor();
  const closeButton = textContains("结束").findOne(); // 结束运行
  if (closeButton.enabled()) {
    click("结束");
    textContains("确定").findOne();
    click("确定");
    console.log("钉钉已被关闭");
    home();
  } else {
    console.log("钉钉未能被正常关闭或不在后台运行");
    home();
  }
  sleep(1000);
}

/**
 * 启动并登陆钉钉
 */
function signIn() {
  openDingtalk();
  setVolume(0); // 设备静音

  if (currentPackage() == PACKAGE_ID_DD) {
    if (currentActivity() == "com.alibaba.android.user.login.SignUpWithPwdActivity") {
      console.info("账号未登录");

      const account = id("et_phone_input").findOne();
      account.setText(ACCOUNT);
      console.log("输入账号");

      const password = id("et_pwd_login").findOne();
      password.setText(PASSWORD);
      console.log("输入密码");

      const privacy = id("cb_privacy").findOne();
      privacy.click();
      console.log("同意隐私协议");

      const btn_login = id("btn_next").findOne();
      btn_login.click();
      console.log("正在登陆...");
      sleep(3000);
    } else {
      console.info("账号已登录");
      sleep(1000);
    }
  }
}

/**
 * 使用 URL Scheme 进入考勤界面
 */
function attendKaoqin() {
  const url_scheme = "dingtalk://dingtalkclient/page/link?url=https://attend.dingtalk.com/attend/index.html";
  if (CORP_ID != "") {
    url_scheme = url_scheme + "?corpId=" + CORP_ID;
  }

  const activity = app.intent({
    action: "VIEW",
    data: url_scheme,
    //flags: [Intent.FLAG_ACTIVITY_NEW_TASK]
  });
  app.startActivity(activity);
  console.log("正在进入考勤界面...");

  textContains("申请").waitFor();
  console.info("已进入考勤界面");
  sleep(1000);

  /*
  let workbenchButton = text("工作台").findOne(DelayTime);
  if (!!!workbenchButton) {
      console.log("钉钉可能不在主界面,重启钉钉");
      shutdownDingtalk();
      openDingtalk();
      workbenchButton = text("工作台").findOne(DelayTime);
  }
  workbenchButton.parent().parent().click();
  console.log("进入工作台");
  const clockinButton = text("考勤打卡").findOne(DelayTime);
  if (!!!clockinButton) {
      postMessage("打开了控制台却没有找到考勤打卡按钮", CLOCKIN_STATE.Fail);
      return;
  }
  clockinButton.click();
  console.log("进入打卡页");
  sleep(1000);
  */
}

// 打卡流程
function doClock() {
  currentDate = new Date();
  console.log("本地时间: " + getCurrentDate() + " " + getCurrentTime());
  console.log("开始打卡流程!");

  brightScreen();
  unlockScreen();
  signIn();

  if (!fastClock()) {
    sleep(1000);
    attendKaoqin();

    if (currentDate.getHours() <= 12) {
      clockIn();
    }
    else {
      clockOut();
    }
  }

  shutdownDingtalk();
  lockScreen();
}

// 急速打卡
function fastClock() {
  console.log("等待10秒的极速打卡");
  const result = textContains("查看打卡结果").findOnce(DelayTime);
  if (!!result) {
    console.log("极速打卡成功");
    return true;
  }
  console.log("未检测到极速打卡通知,执行手动考勤打卡");
  return false;
}

// 上班打卡
function clockIn() {
  console.log("上班打卡...");

  if (checkClockInState()) {
    const text = "已经上班打卡过了";
    console.log(text);
    setStorageData("dingding", "clockResult", text);
    threads.shutDownAll();
    threads.start(function () { sendQQMessage(text); });

    home();
    sleep(1000);
    return;
  }

  const clockinButton = text("上班打卡").findOne(10000);
  if (!!!clockinButton) {
    console.log("没有找到打卡相关按钮,可能是时间设置出错");
    return;
  }
  const result = clockinButton.click();
  const resultText = result ? "检测到打卡成功消息，打卡成功" : "未检测到打卡成功消息或打卡失败";
  console.log(resultText);

  setStorageData("dingding", "clockResult", resultText);
  threads.shutDownAll();
  threads.start(function () { sendQQMessage(resultText); });

  home();
  sleep(1000);
}

/**
 * 下班打卡
 */
function clockOut() {
  console.log("下班打卡...");

  if (checkClockOutState()) {
    const text = "已经下班打卡过了";
    console.log(text);
    setStorageData("dingding", "clockResult", text);
    threads.shutDownAll();
    threads.start(function () { sendQQMessage(text); });

    home();
    sleep(1000);
    return;
  }

  const clockinButton = text("下班打卡").findOne(10000);
  if (!!!clockinButton) {
    console.log("没有找到打卡相关按钮,可能是时间设置出错");
    return;
  }
  const result = clockinButton.click();
  const resultText = result ? "检测到打卡成功消息，打卡成功" : "未检测到打卡成功消息或打卡失败";
  console.log(resultText);

  setStorageData("dingding", "clockResult", resultText);
  threads.shutDownAll();
  threads.start(function () { sendQQMessage(resultText); });

  home();
  sleep(1000);
}

// 检查上班打卡状态
function checkClockInState() {
  const KEYWORD_MATCH = /上班(\d+:\d+)/;
  if (textMatches(KEYWORD_MATCH).exists()) {
    sleep(500);
    let widgets = textMatches(KEYWORD_MATCH).find();
    for (let index = 0; index < widgets.length; index++) {
      let widget = widgets[index];
      let sub1 = widget.parent().child(1).child(0).child(0);
      //let sub2 = widget.parent().child(1).child(0).child(1);
      return sub1.text() != "未打卡";
    }
  }
  return false;
}

// 检查下班打卡状态
function checkClockOutState() {
  const KEYWORD_MATCH = /下班(\d+:\d+)/;
  if (textMatches(KEYWORD_MATCH).exists()) {
    sleep(500);
    let widgets = textMatches(KEYWORD_MATCH).find();
    for (let index = 0; index < widgets.length; index++) {
      let widget = widgets[index];
      let sub1 = widget.parent().child(1).child(0).child(0);
      //let sub2 = widget.parent().child(1).child(0).child(1);
      return sub1.text() != "未打卡";
    }
  }
  return false;
}

// 处理通知
function notificationHandler(n) {
  const packageId = n.getPackageName();   // 获取通知包名
  const abstract = n.tickerText;          // 获取通知摘要
  const text = n.getText();               // 获取通知文本

  // 过滤 PackageId 白名单之外的应用所发出的通知
  if (!filterNotification(packageId, abstract, text)) {
    return;
  }

  // 监听摘要为 "定时打卡" 的通知, 不一定要从 Tasker 中发出通知, 日历、定时器等App均可实现
  if (abstract == "定时打卡" && !suspend) {
    needWaiting = true;
    threads.shutDownAll();
    threads.start(function () { doClock(); });
    return;
  }

  switch (text) {
    case "打卡": // 监听文本为 "打卡" 的通知
      needWaiting = false;
      threads.shutDownAll();
      threads.start(function () { doClock(); });
      break;
    case "查询": // 监听文本为 "查询" 的通知
      threads.shutDownAll();
      threads.start(function () { sendQQMessage(getStorageData("dingding", "clockResult")); });
      break;
    case "暂停": // 监听文本为 "暂停" 的通知
      suspend = true;
      console.warn("暂停定时打卡");
      threads.shutDownAll();
      threads.start(function () { sendQQMessage("修改成功, 已暂停定时打卡功能"); });
      break;
    case "恢复": // 监听文本为 "恢复" 的通知
      suspend = false
      console.warn("恢复定时打卡")
      threads.shutDownAll();
      threads.start(function () { sendQQMessage("修改成功, 已恢复定时打卡功能"); });
      break;
    case "日志": // 监听文本为 "日志" 的通知
      //threads.shutDownAll();
      //threads.start(function () { sendEmail("获取日志", globalLogFilePath, globalLogFilePath); });
      break;
    default: break;
  }
}

/**
 * 发送QQ消息
 * @param {string} message 消息内容
 */
function sendQQMessage(message) {
  console.log("发送QQ消息");

  // brightScreen();
  // unlockScreen();

  app.startActivity({
    action: "android.intent.action.VIEW",
    data: "mqq://im/chat?chat_type=wpa&version=1&src_type=web&uin=" + QQ,
    packageName: "com.tencent.mobileqq",
  });

  // waitForActivity("com.tencent.mobileqq.activity.SplashActivity")

  id("input").findOne().setText(message);
  id("fun_btn").findOne().click();

  home();
  sleep(1000);
}

// ===================== ↓↓↓ 功能函数 ↓↓↓ =======================

function dateDigitToString(num) {
  return num < 10 ? '0' + num : num;
}

function getCurrentTime() {
  const currentDate = new Date();
  const hours = dateDigitToString(currentDate.getHours());
  const minute = dateDigitToString(currentDate.getMinutes());
  const second = dateDigitToString(currentDate.getSeconds());
  const formattedTimeString = hours + ':' + minute + ':' + second;
  return formattedTimeString;
}

function getCurrentDate() {
  const currentDate = new Date();
  const year = dateDigitToString(currentDate.getFullYear());
  const month = dateDigitToString(currentDate.getMonth() + 1);
  const date = dateDigitToString(currentDate.getDate());
  const week = currentDate.getDay();
  const formattedDateString = year + '-' + month + '-' + date + '-' + WEEK_DAY[week];
  return formattedDateString;
}

// 通知过滤器
function filterNotification(bundleId, abstract, text) {
  const check = PACKAGE_ID_WHITE_LIST.some(function (item) { return bundleId == item });
  if (!NOTIFICATIONS_FILTER || check) {
    console.verbose(bundleId);
    console.verbose(abstract);
    console.verbose(text);
    console.verbose("---------------------------");
    return true;
  }
  else {
    return false;
  }
}

// 保存本地数据
function setStorageData(name, key, value) {
  const storage = storages.create(name);  // 创建storage对象
  storage.put(key, value);
}

// 读取本地数据
function getStorageData(name, key) {
  const storage = storages.create(name);
  if (storage.contains(key)) {
    return storage.get(key, "");
  }
  // 默认返回undefined
}

// 删除本地数据
function delStorageData(name, key) {
  const storage = storages.create(name);
  if (storage.contains(key)) {
    storage.remove(key);
  }
}

// 获取应用版本号
function getPackageVersion(bundleId) {
  importPackage(android.content);
  const packageManager = context.getPackageManager();
  const packageInfo = packageManager.getPackageInfo(bundleId, 0);
  return packageInfo.versionName;
}

// 屏幕是否为锁定状态
function isDeviceLocked() {
  importClass(android.app.KeyguardManager);
  importClass(android.content.Context);
  const km = context.getSystemService(Context.KEYGUARD_SERVICE);
  return km.isKeyguardLocked();
}

// 设置媒体和通知音量
function setVolume(volume) {
  device.setMusicVolume(volume);
  device.setNotificationVolume(volume);
  console.verbose("媒体音量:" + device.getMusicVolume());
  console.verbose("通知音量:" + device.getNotificationVolume());
}
